#include "usart_protocol_subset_update.h"
#include "net_protocol_update.h"
#include "eth_app_network.h"
#include "func_shell.h"
#include "global.h"
#include "w25qxx.h"
#include "global_protocol_update.h"
/*
	通过串口下发固件包给子设备，让子设备升级程序

*/


#define data_send(buff,len) usart_send(shell_struct.pu,buff,len);			//方便替换发送接口
//#define data_send net_send_data			//方便替换发送接口

uint8_t printf_flag=0;
void update_printf(const char *format, ...) {

    if(printf_flag!=0)
        printf(format);

}


//最长应答67
#define PROTOCOL_RECV_MAX 80
static uint8_t protocol_recv_buf[PROTOCOL_RECV_MAX];
static uint8_t protocol_update_check( unsigned char *unpack_data,uint16_t unpack_length);


uint16_t subset_bin_size;			//固件包大小 单位: 字节
//uint8_t deal_update_flag=0;

static uint16_t step = 0;
static uint16_t count = 0;
static uint16_t data_length = 0;

uint16_t recv_subset_data_one_by_one(uint8_t data)
{

#ifdef PRINT_DATA
    update_printf("%02X", data);
#endif

    if (step == 0 && data == 0xfe) //接收到包头
    {
        protocol_recv_buf[step] = data;
        ++step;
    }
    else if (step == 1)                //接收到指令
    {
        protocol_recv_buf[step] = data;
        ++step;
    }
    else if (step == 2 ||step == 3)              //接收到length（数据长度）
    {
        protocol_recv_buf[step] = data;
        ++count;
        ++step;
        if (count == 2)
        {
            count = 0;
            data_length = u8_2_u16(&protocol_recv_buf[2]);
            if(data_length >PROTOCOL_RECV_MAX)
            {
                //update_printf("----> data_length too long %d\n",data_length);
                step=0;
                count = 0;
                return step;
            }
//              if(len==0)  //处理无真实数据体的包
//                  i=5;
        }
    }
    else if ((step >= 4) && (data_length > 0))
    {
        data_length--;
        protocol_recv_buf[step++] = data;
    }
    else if (step >= 4)
    {
        protocol_recv_buf[step] = data;
        ++count;
        ++step;
        if (count >= 2)
        {
            /*********  输出接收到的数据        ********/
//          for(int j=0;j<i;j++){
//              update_printf("tmp: %x ",tmp[i]);
//          }
            protocol_update_check(protocol_recv_buf, step);        //传入蓝牙数据包
            count = 0;
            step = 0;
        }

    }
    else
    {
        step = 0;
        count = 0;
        data_length = 0;
    }

    return step;
}
static uint16_t pro_send_package(uint8_t _command,uint8_t* _pInputDataBuf,uint16_t _dataLength)
{
    uint8_t pos=0;
    protocol_update_buff[pos++] = 0xFE;
    protocol_update_buff[pos++] = _command;
    protocol_update_buff[pos++] = _dataLength >> 8;
    protocol_update_buff[pos++] = _dataLength;

    memcpy(&protocol_update_buff[pos],_pInputDataBuf,_dataLength);
//	for(int i=0;i<_dataLength;i++)
//	{
//		_pOutputDataBuf[cnt+i] = _pInputDataBuf[i];
//	}
    pos+=_dataLength;
    uint16_t crc16 = get_crc(protocol_update_buff+1,3+_dataLength);
    protocol_update_buff[pos++] = crc16 >>8;
    protocol_update_buff[pos++] = crc16 ;

    data_send(protocol_update_buff,pos);

    return pos;
}

typedef struct
{
    unsigned short cmd;
    uint8_t (*handler)(uint8_t * ppack,uint16_t length);
} rst_cmd_handler;




static uint8_t New_version_notification(char* new_soft_ver,char* curr_hard_ver,uint8_t curr_dev_type,uint8_t dev_addr) {
    uint8_t sendbuff[35] = {0};
    int pos=0;
    int h,l;
    sscanf(PRO_UPDATE_VER,"V%d.%d",&h,&l);
    sendbuff[pos++]=h;
    sendbuff[pos++]=l;
    strcpy((char*)&sendbuff[pos],new_soft_ver);
    pos+=10;
    strcpy((char*)&sendbuff[pos],curr_hard_ver);
    pos+=10;
    sendbuff[pos++]=curr_dev_type;				//设备类型

    sendbuff[pos++]=(uint8_t)(dev_addr>>8);
    sendbuff[pos++]=(uint8_t)(dev_addr);

    sendbuff[pos++]=(uint8_t)(A_PACK_SIZE>>8);
    sendbuff[pos++]=(uint8_t)(A_PACK_SIZE);


    subset_bin_size=ef_get_env_int("subset_bin_size");	//升级包大小 单位：字节

    sendbuff[pos++]=(uint8_t)((subset_bin_size/A_PACK_SIZE)>>8);			//升级包数
    sendbuff[pos++]=(uint8_t)(subset_bin_size/A_PACK_SIZE);

    sendbuff[pos++]=(uint8_t)(CHECK_CODE>>8);
    sendbuff[pos++]=(uint8_t)(CHECK_CODE);


    pro_send_package(NEW_VERSION_NOTIFICATION,sendbuff,pos);
		return 0;
}


static uint8_t get_soft_version_response(uint8_t *pack, uint16_t _length)
{
    //uint8_t sendbuff[35] = {0};
    //deal_update_flag=0;
    //uint16_t pos;
    char* save_subset_soft_ver=ef_get_env("subset_soft_ver");
    char* save_subset_hard_ver=ef_get_env("subset_hard_ver");
    uint8_t save_dev_type=ef_get_env_int("subset_dev_type");

    char* recv_subset_soft_ver=(char*)&pack[1];
    char* recv_subset_hard_ver=(char*)&pack[11];
    uint8_t recv_dev_type=pack[21];

    uint16_t dev_addr=u8_2_u16(&pack[22]);

    update_printf("recv_soft_ver: %s, save_soft_ver: %s\n",recv_subset_soft_ver,save_subset_soft_ver);
    update_printf("recv_hard_ver: %s, save_hard_ver: %s\n",recv_subset_hard_ver,save_subset_hard_ver);

    if(strncmp(save_subset_soft_ver,recv_subset_soft_ver,strlen(save_subset_soft_ver))!=0&&\
            strncmp(save_subset_hard_ver,recv_subset_hard_ver,strlen(save_subset_hard_ver))==0&&\
            save_dev_type==recv_dev_type)
    {

        New_version_notification(save_subset_soft_ver,save_subset_hard_ver,save_dev_type,dev_addr);

    }
    else
    {
        update_printf("save_subset_ver check ERR\n");		//版本号相同 不执行升级，（设备将一直等待，需要添加超时退出升级）
				
    }

    return 0;
}

static uint8_t New_version_notification_response(uint8_t *pack, uint16_t _length)
{
    uint16_t ack_code=u8_2_u16(&pack[0]);
    if(ack_code==0)
    {
        update_printf("OK device will update, wait dev request ...\n");
    }
    else
    {
        update_printf("ERR device refuse update: %d\n",ack_code);
    }
    return 0;
}

void issue_bin(uint16_t package_num) {
    /*******		不使用 pro_send_package 打包函数，可节省500字节缓存区		*********/
    uint16_t read_package_size=0;
    if((subset_bin_size-((package_num+1)*A_PACK_SIZE))>=A_PACK_SIZE)		// 包总大小 - ((1+包号)*512) >= 512
        read_package_size=A_PACK_SIZE;
    else
    {
        read_package_size=subset_bin_size-(package_num*A_PACK_SIZE);
        update_printf("The last packet\n");
        //deal_update_flag=1;
    }

    uint16_t _dataLength=1+2+read_package_size;			//处理结果一字节 + 包号2字节 + 分包大小

    uint8_t pos=0;
    protocol_update_buff[pos++] = 0xFE;
    protocol_update_buff[pos++] = REQUEST_UPDATE_PACKAGE;
    protocol_update_buff[pos++] = _dataLength >> 8;
    protocol_update_buff[pos++] = _dataLength;

    protocol_update_buff[pos++] = 0x00;		//处理成功
    protocol_update_buff[pos++] = (uint8_t)(package_num>>8);
    protocol_update_buff[pos++] = (uint8_t)package_num;

    __disable_irq();	//关中断
    //memcpy(&protocol_update_buff[pos],_pInputDataBuf,_dataLength);
    EN25QXX_Read(&protocol_update_buff[pos],BK_APP_ADDR+(package_num*A_PACK_SIZE),read_package_size);
    pos+=read_package_size;
    uint16_t crc16 = get_crc(protocol_update_buff+1,3+_dataLength);
    __enable_irq();	//开中断

    protocol_update_buff[pos++] = crc16 >>8;
    protocol_update_buff[pos++] = crc16 ;

    data_send(protocol_update_buff,pos);
}


static uint8_t request_update_package_response(uint8_t *pack, uint16_t _length)
{
    uint16_t package_num=u8_2_u16(&pack[10]);
    update_printf("dev request pack num: %d\n",package_num);
    if((package_num>=0)&&(package_num<=((ef_get_env_int("subset_bin_size")/A_PACK_SIZE)+1)))			//防止超出固件大小
    {
        issue_bin(package_num);			//下发一片固件包
    }
    else
    {
        update_printf("ERR dev request pack num: %d\n",package_num);
    }
    return 0;
}
static uint8_t pack_down_status_response(uint16_t download_result) {
    uint8_t result=download_result;
    pro_send_package(UPLOAD_UPDATE_PACK_DOWN_STATUS,&result,1);
return 0;
}
void device_deal_update() {
    pro_send_package(DEAL_UPDATE,0,0);


}
static uint8_t upload_update_pack_down_status(uint8_t *pack, uint16_t _length)
{
    uint16_t download_result=u8_2_u16(&pack[0]);
    if(download_result==0x00) {
        update_printf("download result OK\n");
        device_deal_update();

    }
    else
    {
        update_printf("download result ERR: %d\n",download_result);

    }

//		if(deal_update_flag==1)
//		{


//		}else
//			pack_down_status_response(download_result);
		return 0;
}

static uint8_t deal_update_response(uint8_t * pack,uint16_t _length) //执行升级
{
    uint16_t result=u8_2_u16(&pack[0]);
    update_printf("deal_update result: %d\n",result);

}


static const rst_cmd_handler  cmd_handler[] =
{
    {GET_SOFT_VERSION, &get_soft_version_response},
    {NEW_VERSION_NOTIFICATION,&New_version_notification_response},
    {REQUEST_UPDATE_PACKAGE,&request_update_package_response},
    {UPLOAD_UPDATE_PACK_DOWN_STATUS,upload_update_pack_down_status},
    {DEAL_UPDATE,&deal_update_response},
};


static uint8_t protocol_update_check( unsigned char *unpack_data,uint16_t unpack_length)
{
    uint16_t crc = (protocol_recv_buf[unpack_length-2]<<8 | protocol_recv_buf[unpack_length-1]);
    uint16_t cmd;
    uint16_t data_length = (uint16_t)(protocol_recv_buf[2]<<8 | protocol_recv_buf[3]);
    uint16_t cal_crc16 = get_crc(unpack_data+1,3+data_length);

    if(crc != cal_crc16)
    {
        update_printf("crc error :get crc16 %x   -    cal the crc16 = %x\n",crc,cal_crc16);
        return 1;
    }
    for(int i=0; i<sizeof(cmd_handler)/sizeof(rst_cmd_handler); i++)
    {
        cmd =unpack_data[1];
        if(cmd == cmd_handler[i].cmd)
        {
            if(cmd_handler[i].handler == NULL)
                return 1;
            cmd_handler[i].handler(&unpack_data[4],unpack_length-(4+2));			//仅仅传入信息体，去掉头4字节和尾巴2字节
            return 0;
        }
    }

    return 0;
}

uint8_t usart_get_subset_soft_version()
{
    update_printf("get subset dev ver\n");
    pro_send_package(GET_SOFT_VERSION,0,0);
    return 0;
}


static int sub_up(uint8_t argc,char **argv) {
    usart_get_subset_soft_version();
return 0;
}
//CMD_EXPORT(sub_up,sub update);

static int sub_up_printf(uint8_t argc,char **argv) {
    //sscanf(buf,"sub_update_printf %d",&printf_flag);
    printf_flag=atoi(argv[1]);
	return 0;
}
//CMD_EXPORT(sub_up_printf,set print);

